package kotlinx.coroutines

import kotlinx.coroutines.scheduling.DefaultIoScheduler
import kotlinx.coroutines.scheduling.DefaultScheduler
import java.util.concurrent.atomic.AtomicReference

/**
 * 外部注入的协程Dispatcher，用于解决Android华为协程库线程创建过多，超出500个后导致运行时Crash，
 * 所以使用外部注入的[CoroutineDispatcher]，作为协程线程池的实现，避免协程内部创建线程
 */
public interface CoroutineHostApi {

    public fun ioDispatcher(): CoroutineDispatcher

    public fun defaultDispatcher(): CoroutineDispatcher

    public fun log(tag: String, messageBlock: () -> String)
}

public object CoroutineHostConfiguration {

    private const val TAG_COROUTINE_DEBUG = "COROUTINE_DEBUG"

    /**
     * 宿主设置的[CoroutineHostApi]对象，通过[AtomicReference]以及CAS保证线程安全
     */
    private var hostApi = AtomicReference<CoroutineHostApi?>(null)

    /**
     * CAS设置宿主对象，返回设置是否成功
     */
    public fun setCoroutinesHostApi(host: CoroutineHostApi): Boolean =
        hostApi.compareAndSet(null, host)

    /**
     * 替换原有的IODispatcher对象
     */
    internal fun getIODispatcher(): CoroutineDispatcher =
        hostApi.get()?.ioDispatcher() ?: DefaultIoScheduler

    /**
     * 替换原有的DefaultDispatcher对象
     */
    internal fun getDefaultDispatcher(): CoroutineDispatcher =
        hostApi.get()?.defaultDispatcher() ?: DefaultScheduler

    internal fun log(tag: String, messageBlock: () -> String) =
        hostApi.get()?.log("[${TAG_COROUTINE_DEBUG}:${tag}]", messageBlock)
}